using GEM.Infrastructure;
using GEM.Application;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using NLog.Web;
using NLog;
using GEM.Application.Contracts.Jwt;
using GEM.Infrastructure.Extensions;

var logger = NLog.LogManager.Setup().LoadConfigurationFromFile("nlog.config").GetCurrentClassLogger();

try
{
    var builder = WebApplication.CreateBuilder(args);

    // 替换默认日志工厂为NLog（推荐写法）
    builder.Logging.ClearProviders();
    builder.Host.UseNLog();

    //注册控制器模式
    builder.Services.AddControllers();

    // 注册基础设施层服务,实现依赖注入
    builder.Services.AddInfrastructure(builder.Configuration);

    //注册应用层服务，实现依赖注入
    builder.Services.AddApplication(builder.Configuration);

    var jwtSettings = builder.Configuration.GetSection("Jwt").Get<JwtSettings>();

    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
#pragma warning disable CS8602 // 解引用可能出现空引用。
        options.TokenValidationParameters = new TokenValidationParameters
        {
            // 基本验证
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,

            // 合法值配置
            ValidIssuer = jwtSettings.Issuer,
            ValidAudience = jwtSettings.Audience,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Key)),

            // 其他高级选项
            ClockSkew = TimeSpan.Zero, // 严格过期时间（默认有5分钟缓冲）
            RequireExpirationTime = true // 必须包含过期时间
        };
#pragma warning restore CS8602 // 解引用可能出现空引用。
    });

    var app = builder.Build();

    // 启用跨域(CORS中间件必须在认证和授权之前)
    app.UseCors(CorsExtensions.DefaultCorsPolicyName);

    // 启用认证和授权中间件（顺序很重要！）
    app.UseAuthentication(); // 必须先于 UseAuthorization
    app.UseAuthorization();

    // 将控制器路由映射到应用程序的请求管道中
    app.MapControllers();

    app.Run();
}
catch (Exception ex)
{
    logger.Error(ex, "程序启动异常");
    throw;
}
finally
{
    NLog.LogManager.Shutdown();
}